/*
 * Copyright (c) 2005, 2014 vacoor
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.vacoor.nothing.misc.dts.oo.comp;

import com.sun.star.beans.PropertyValue;
import com.sun.star.frame.XComponentLoader;
import com.sun.star.frame.XStorable;
import com.sun.star.lang.XComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vacoor.nothing.common.util.IOUtils;
import org.vacoor.nothing.misc.dts.oo.io.SeekableInputStream;
import org.vacoor.nothing.misc.dts.oo.util.UnoUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.Channels;

/**
 * @author vacoor
 * @see <decode href="https://wiki.openoffice.org/wiki/API/Tutorials/PDF_export">OOo PDF Export</decode>
 * @see <decode href="http://www.openoffice.org/api/docs/common/ref/com/sun/star/document/MediaDescriptor.html">OOo MediaDescriptor</decode>
 */
public abstract class UnoTranslator extends UnoReadWriteSupport {
    private static final Logger LOG = LoggerFactory.getLogger(UnoTranslator.class);

    protected final String extension;

    protected UnoTranslator(String extension) {
        this.extension = extension;
    }

    protected void translate(UnoBridge unoBridge, File source, PropertyValue[] loadProperties, OutputStream destination, PropertyValue[] storeProperties) throws Exception {
        XComponentLoader loader = unoBridge.createRemoteComponentLoader();

        LOG.info("加载 {}", source);
        // TODO 如果是文本文件可能无法获取, 需要有扩展名
        XComponent doc = loadForm(loader, source, loadProperties);
        String filterName = UnoExpFilterRegistry.getFilterName(doc, extension);

        if (filterName == null) {
            throw new UnsupportedOperationException("无法识别输出文件格式, " + " extension: " + extension);
        }

        LOG.info("开始转换 {}, 使用filter: {}", source, filterName);
        XStorable xStorable = UnoUtils.$(XStorable.class, doc);
        storeTo(xStorable, destination, UnoUtils.of(storeProperties, UnoUtils.of("FilterName", filterName)));

        UnoUtils.disposeIf(doc);
        UnoUtils.closeIf(doc);

        LOG.info("转换成功: {} --> {}", source, destination);
    }

    /**
     *
     */
    protected void translate(UnoBridge unoBridge, InputStream source, PropertyValue[] loadProperties, OutputStream destination, PropertyValue[] storeProperties) throws Exception {
        File tempFile = File.createTempFile("UnoTranslator", ".tmp");
        IOUtils.flow(Channels.newChannel(source), new FileOutputStream(tempFile).getChannel(), true, true);
        translate(unoBridge, tempFile, loadProperties, destination, storeProperties);
        tempFile.delete();
    }

    /**
     * 发现使用 Java InputStream 方式效率要低很多, 该方法已经改为调用
     * {@link #translate(UnoBridge, File, PropertyValue[], OutputStream, PropertyValue[])}
     *
     * @deprecated
     */
    protected void translate(UnoBridge unoBridge, SeekableInputStream source, PropertyValue[] loadProperties, OutputStream destination, PropertyValue[] storeProperties) throws Exception {
        translate(unoBridge, (InputStream) source, loadProperties, destination, storeProperties);
    }
}
